home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
flxlstc.exe
/
FLEXLIST.CKR
< prev
next >
Wrap
Text File
|
1990-12-05
|
24KB
|
1,124 lines
/*
flexlist.ckr
10-4-90
Homogeneous-heterogeneous
hybrid stack-queue-list-array generic class.
K&R C
Copyright 1990
John W. Small
All rights reserved
PSW / Power SoftWare
P.O. Box 10072,
McLean, Virginia 22102 8072
(703) 759-3838
*/
#include <flexlist.hkr> /* size_t, void, const */
#ifdef ANSI_C_STD_LIB
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* memcpy(), memset() */
#else
extern void *malloc(/* size_t size */);
extern free(/* void *block */);
void *memcpy(dest, src, n)
void *dest;
const void *src;
size_t n;
{
if (dest && src && n)
while (n--)
dest[n] = src[n];
return dest;
}
void *memset(s, c, n)
void *s;
int c;
size_t n;
{
if (s && n)
while (n--)
s[n] = c;
return s;
}
#endif
/* String variant FlexNode virtual functions */
/*
FNnew() is called by FlexList functions (primitives)
that need to allocate new variant length FlexNodes,
e.g. FLpushD(), FLinsQD(), FLinsD(), FLinsSortD().
A pointer to the data to be placed in the new node
is passed to FNnew(). Your FNnew() function must
decide how large that data is and allocate a new
FlexNode big enough to hold that data, i.e.
FlexN N = malloc(sizeof(FlexNode) +
sizeofYourData - 1).
Your FNnew() function must also copy that data to
the new node. "D" is never NULL!
Please note that FNnew() could call a known function
pointer (function) in the data to determine its size.
It could also call another function to copy/
initialize the FlexNode data area from the data.
Data that contains its own functions for interfacing
with itself are called objects. Thus FlexLists can
be made to hold polymorphic objects via the
virtual function table functionology.
Study all four virtual functions FNnew(), FNwrite(),
FNread(), and FNdestruct() for strings and how they
are called by the various FlexList functions to get
a better understanding of variant FlexLists.
*/
static FlexN FNnewStr(D)
const void *D;
{
FlexN N;
size_t i;
for (i = 0; D[i++]; /* no reinit */)
/* null statement */;
if ((N = (FlexN) malloc(sizeof(FlexNode)+i-1)) != FlexN0)
memcpy(N->data,D,i);
return N;
}
/* FNwrite() is called by FLstoreD() to write variant data
to a variant FlexNode. FNwrite() returns true if
the write is successful. Make sure the new data doesn't
write pass the end of the old. "ND" and "D" are never
NULL! */
static int FNwriteStr(ND, D)
void *ND;
const void *D;
{
while (*ND)
if ((*ND++ = *D++) == '\0')
break;
return 1;
}
/* FNread() is called by FLtopD(), FLnextD(),
FLprevD(), and FLrecallD() to read variant data
from a variant FlexNode. FNread() returns true if
the read is successful or if there is no place to
read the data to. "ND" and "D" are never NULL! */
static int FNreadStr(ND, D)
const void *ND;
void *D;
{
while ((*D++ = *ND++) != '\0')
/* null statement */;
return 1;
}
/* FNdestruct() is called by FLclear(), FLdelete() via
Flclear(), FLpopD(), and FLdelD() to destruct
variant data in a FlexNode. Please note that
references to suballocated memory may be copied
to the outgoing data structure instead of being
cloned and then deallocated. You must keep any
scheme straight though. FLclear() always passes
NULL to the second parameter of FNdestruct() via
a call to FLpopD(L,0), however, so any
suballocated memory must be freed in that case!
"ND" is never NULL but "D" can be! */
static int FNdestructStr(ND, D)
void *ND;
void *D;
{
if (D)
while ((*D++ = *ND++) != '\0')
/* null statement */;
return 1;
}
/* Any of the virtual functions can be absent. The FlexList
functions that call them will simply return a failure
indication. Use FNnew0, FNwrite0, FNread0, and/or
FNdestruct0 as zero initializers. */
FlexNodeVFT FlexNodeStrVFT = {
FNnewStr, FNwriteStr, FNreadStr, FNdestructStr };
/* FlexList constructors/destructor - static headers */
#define FLzero(L) memset((void *)(L),0,sizeof(FlexList)-1)
FlexL FLfixed(L, sizeofNodeData)
FlexL L;
size_t sizeofNodeData;
{
if (!L)
return L;
/* (void) */ FLzero(L);
if (!sizeofNodeData || sizeofNodeData
> FLmaxSizeofNodeData)
return FlexL0;
L->maxNodes = FLmaxMaxNodes;
L->sizeofNodeData = sizeofNodeData;
L->sizeofNode = sizeof(FlexNode)
+ sizeofNodeData - 1;
L->sorted = 1;
return L;
}
FlexL FLunpack(L, sizeofCell, cells, array)
FlexL L;
size_t sizeofCell;
unsigned cells;
const void *array;
{
if (!L)
return L;
/* (void) */ FLzero(L);
if ((sizeofCell > FLmaxSizeofNodeData) ||
!sizeofCell || !cells || !array)
return FlexL0;
L->maxNodes = FLmaxMaxNodes;
L->sizeofNodeData = sizeofCell;
L->sizeofNode = sizeof(FlexNode)
+ sizeofCell - 1;
for (;cells && FLinsQD(L,array); cells--)
array = (char *) array + sizeofCell;
return L;
}
FlexL FLvariant(L, vft)
FlexL L;
FlexNVFT vft;
{
if (!L)
return L;
/* (void) */ FLzero(L);
if (!vft)
return FlexL0;
L->maxNodes = FLmaxMaxNodes;
L->sorted = 1;
L->vft = vft;
return L;
}
int FLclear(L)
FlexL L;
{
while (FLpopD(L,(void *)0))
/* null statement */;
if (L) if (!L->nodes)
return (L->sorted = 1);
return 0;
}
/* FlexList constructors/destructor - dynamic headers */
/* FlexList headers are flagged as dynamic if and only if
FLDdestruct != NULL. FLDmalloced() is the default
function pointer whenever one isn't specified. */
/* ARGSUSED */
static int FLDmalloced(LD)
void *LD;
{ /* LD is intentionally unused! */
return 1;
}
static FlexL FLnew(sizeofLocalData, FLDdestruct)
size_t sizeofLocalData;
int (*FLDdestruct)(/* void *LD */);
{
FlexL L;
if (sizeofLocalData > FLmaxSizeofLocalData)
return FlexL0;
L = (FlexL) malloc(sizeof(FlexList) +
sizeofLocalData - 1);
if (L) {
/* (void) */ FLzero(L);
if (FLDdestruct)
L->FLDdestruct = FLDdestruct;
else
L->FLDdestruct = FLDmalloced;
}
return L;
}
FlexL FLfixedNew(sizeofNodeData, sizeofLocalData,
FLDdestruct)
size_t sizeofNodeData;
size_t sizeofLocalData;
int (*FLDdestruct)(/* void *LD */);
{
FlexL L;
if (!sizeofNodeData || sizeofNodeData >
FLmaxSizeofNodeData)
return FlexL0;
if ((L = FLnew(sizeofLocalData,FLDdestruct))
!= FlexL0) {
L->maxNodes = FLmaxMaxNodes;
L->sizeofNodeData = sizeofNodeData;
L->sizeofNode = sizeof(FlexNode)
+ sizeofNodeData - 1;
L->sorted = 1;
}
return L;
}
FlexL FLunpackNew(sizeofCell, cells, array,
sizeofLocalData, FLDdestruct)
size_t sizeofCell;
unsigned cells;
const void *array;
size_t sizeofLocalData;
int (*FLDdestruct)(/* void *LD */);
{
FlexL L;
if ((sizeofCell > FLmaxSizeofNodeData) ||
!sizeofCell || !cells || !array)
return FlexL0;
if ((L = FLnew(sizeofLocalData,FLDdestruct))
!= FlexL0) {
L->maxNodes = FLmaxMaxNodes;
L->sizeofNodeData = sizeofCell;
L->sizeofNode = sizeof(FlexNode)
+ sizeofCell - 1;
for (;cells && FLinsQD(L,array); cells--)
array = (char *) array + sizeofCell;
}
return L;
}
FlexL FLvariantNew(vft, sizeofLocalData, FLDdestruct)
FlexNVFT vft;
size_t sizeofLocalData;
int (*FLDdestruct)(/* void *LD */);
{
FlexL L;
if (!vft)
return FlexL0;
if ((L = FLnew(sizeofLocalData,FLDdestruct))
!= FlexL0) {
L->maxNodes = FLmaxMaxNodes;
L->sorted = 1;
L->vft = vft;
}
return L;
}
int FLdelete(Lptr)
FlexL *Lptr;
{
if (!Lptr)
return 0;
if (!(*Lptr)->FLDdestruct)
return 0;
if (!(*((*Lptr)->FLDdestruct))((*Lptr)->data))
return 0;
if (!FLclear(*Lptr))
return 0;
free(*Lptr);
*Lptr = FlexL0;
return 1;
}
/* FlexList header functions */
int FLsetMaxNodes(L, maxNodes)
FlexL L;
unsigned maxNodes;
{
if (L)
if (maxNodes >= L->nodes) {
L->maxNodes = maxNodes;
return 1;
}
return 0;
}
int FLsetCompare(L, compare)
FlexL L;
int (*compare)(/* const void *D1, const void *D2 */);
{
if (L) {
L->compare = compare;
L->sorted = 0;
return 1;
}